/*
 * implementation of environment data structure.
 */

#include <debug.h>
#include <base.h>
#include "env.h"

LocalEnv emptyLocalEnv = NULL ;
Environment emptyEnv = &emptyLocalEnv ;

void schemeObjectCopy(Environment target, int tgtStart, Environment source, int srcStart, int amount)
{
	int i ;
	for (i = 0 ; i < amount ; i++)
		target[tgtStart + i] = source[srcStart + i] ;
}

Environment extendEnv(Environment env, LocalEnv local)
{
	int envSize=0;
	Environment result ;
	while (env[envSize]!= NULL)
		{envSize++;}
	DEBUG_TRACE("env size is %d", envSize) ;

	result = (Environment)autoMalloc(sizeof(LocalEnv) * (envSize+2)) ;

	schemeObjectCopy(result, 1, env, 0, envSize+1) ;
	result[0] = local ;
	return result ;
}

string localEnvToString(SchemeObject** objects, Amount size)
{
	int i ;
	string result = stringAlloc(150) ;
	result[0] = '\0' ;
	if (size >= 1)
		strcat(result, sobToString(objects[0])) ;
	for (i = 1 ; i < size; i++)
	{
		strcat(result, ", ") ;
		strcat(result, sobToString(*(objects-i))) ;
	}
	return result ;
}

LocalEnv makeLocalEnv(SchemeObject** args, Amount size)
{
	int i ;
	DEBUG_ENTER("%lu elements: (%s)", size, localEnvToString(args, size)) ;
	LocalEnv local = (LocalEnv)autoMalloc(sizeof(SchemeObject*) * (size)) ;
	for (i = 0 ; i < size ; i++)
		local[i] = *(args-i) ;
	return local ;
}

SchemeObject* getBoundVar(Environment env, unsigned major, unsigned minor)
{
	DEBUG_TRACE("major = %d, minor = %d", major, minor) ;
	SchemeObject* result ;
	LocalEnv argList = env[major] ;
	DEBUG_ASSERT(argList != NULL) ;
	result = argList[minor] ;
	DEBUG_ASSERT(result != NULL) ;
	DEBUG_EXIT("result: %s",  sobToString(Sob(result))) ;
	return result ;
}

void setBoundVar(Environment env, unsigned major, unsigned minor, SchemeObject* val)
{
	DEBUG_TRACE("major = %d, minor = %d", major, minor) ;
	LocalEnv argList = env[major] ;
	DEBUG_ASSERT(argList != NULL) ;
	DEBUG_ASSERT(argList[minor] != NULL) ;
	argList[minor] = val ;
}
